package personal.zq.practice.common.bo;

/**
 * 单例（Singleton）模式：某个类只能生成一个实例，该类提供了一个全局访问点供外部获取该实例，其拓展是有限多例模式。
 * 优点：只有一个实例，节约了内存资源，提高了系统性能；
 * 缺点：没有抽象层，不能扩展;    职责过重，违背了单一性原则。
 *
 * @author zhangqing
 * @version 1.0
 * @date 2022/8/26
 */
public class Singleton {

    private static Singleton instance = null;

    /* 私有构造方法，防止被实例化 */
    private Singleton() {
    }

    /* 如果该对象被用于序列化，可以保证对象在序列化前后保持一致 */
    public Object readResolve() {
        return getInstance4();
    }

    /**
     * 无线程安全
     *
     * @return
     */
    /* 静态工程方法，创建实例 */
    public static Singleton getInstance1() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    /**
     * 用法加锁，性能低
     * @return
     */
    public static synchronized Singleton getInstance2() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    /**
     * 对象加锁，性能低
     *
     * 创建对象和赋值操作是异步的，第一次使用时可能还没初始化
     *
     * @return
     */
    public static Singleton getInstance3() {
        if (instance == null) {
            synchronized (instance) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    /**
     * 此处使用一个内部类来维护单例
     * 单例模式使用内部类来维护单例的实现，JVM内部的机制能够保证当一个类被加载的时候，这个类的加载过程是线程互斥的。
     * 这样当我们第一次调用getInstance的时候，JVM能够帮我们保证instance只被创建一次，
     * 并且会保证的赋值给instance的内存初始化完毕，这样我们就不用担心分配了空间但未初始化的问题。
     * 同时该方法也只会在第一次调用的时候使用互斥机制，这样就解决了低性能问题
     */
    private static class SingletonFactory {
        private static Singleton instance = new Singleton();
    }

    /* 获取实例 */
    public static Singleton getInstance4() {
        return SingletonFactory.instance;
    }
}

